from channels.generic.websocket import AsyncWebsocketConsumer
import logging
logger = logging.getLogger(__name__)
from channels.db import database_sync_to_async
import json
from .models import ChatRoom
from django.utils import timezone
from .tasks import save_room_message,fetch_deepseek_reply
class ChatConsumer(AsyncWebsocketConsumer):
    def __init__(self):
        super().__init__(self)
        self.room_id = None
        self.user = None
        self.room = None
        self.group_id = None
        self.api = None
    async def connect(self):
        self.room_id = self.scope['url_route']['kwargs']['room_id']
        self.user = self.scope['user']  # 这里是user模型
        self.api = self.user.deepseekapi
        if not self.user.is_authenticated:  # 这个is_authenticated是django自带的 判断是否登录
            await self.close(code=4001)  # close会触发 disconnect
            return
        self.room = await self.get_room(self.room_id)
        if not self.room:
            logger.warning(f"用户{self.user.username}尝试访问不存在的房间")
            await self.close(code=4002)
            return
        if not await self.check_user_can_join():
            logger.warning(f"用户{self.user.username}尝试访问被拉黑的房间")
            await self.close(code=4003)
            return
        if not await self.user_contain():
            await self.add_member(self.user)
        self.group_id = f'chat_{self.room_id}'
        # room_id只适合外键，不可用
        await self.channel_layer.group_add(self.group_id, self.channel_name)
        # channel_name是 WebSocket 连接的唯一通道标识符，由 Channels 自动生成（如 "specific.abcd1234!"）
        # 标识唯一的客户端连接。当群组广播消息时，Channels 会根据 channel_name 找到对应的连接并推送消息。
        # 非要加channel_name的目的是保持 API 的灵活性和明确性，支持非当前连接操作。
        # 避免隐藏行为，减少意外错误。
        await self.accept()
        logger.info(f"User {self.user.username} connected to room {self.room.name}")
        await self.send_system_message(f'{self.user.username} 加入了聊天室')

    @database_sync_to_async
    def get_room(self,room_id):
        try:
            return ChatRoom.objects.filter(id=room_id).first()
        except ChatRoom.DoesNotExist:
            return None

    @database_sync_to_async
    def add_member(self,user):
        return self.room.members.add(user)

    @database_sync_to_async
    def async_remove_member(self,user):
        return self.room.remove_member(user)

    @database_sync_to_async
    def check_user_can_join(self):
        return self.room.user_can_join(self.user)

    @database_sync_to_async
    def user_contain(self):
        return self.room.members.contains(self.user)
    async def disconnect(self, code):
        if self.group_id:
            await self.channel_layer.group_discard(self.group_id,self.channel_name)
        if self.room:
            # await self.async_remove_member(self.user)
            await self.send_system_message(f'{self.user.username} 离开了聊天室')
        logger.info(f"用户 {self.user.username} 断开了 {self.room.name} 的连接，断开代码是 {code}")

    async def receive(self, text_data=None, bytes_data=None):
        # text_data和bytes_data只能有一个 第一个是文本，第二个是文件
        try:
            data = json.loads(text_data)
            msg = data.get('message')
            require_deepseek = data.get('require_deepseek',False)
            if not msg or not msg.strip():
                return

            event = {
                'type':'chat_message',
                'message': msg,
                'timestamp': timezone.now().isoformat(),
                'sender': self.user.username,
                'require_deepseek': require_deepseek,
                'is_deepseek': False
            }

            await self.channel_layer.group_send(self.group_id, event)
            save_room_message.delay(
                room_id = self.room_id,
                user_id = self.user.id,
                message = msg,
                timestamp = event['timestamp'],
                is_deepseek=False
            )
            if require_deepseek:
                fetch_deepseek_reply.delay(
                    group_id=self.group_id,
                    room_id = self.room_id,
                    user_name=event['sender'],
                    message=msg,
                    api=self.api
                )
        except json.JSONDecodeError:
                logger.error("Invalid JSON received")
        except Exception as e:
            logger.exception("Error processing message")
    async def chat_message(self,event):
        await self.send(text_data=json.dumps(event))
    async def system_message(self,event):
        await self.send(text_data=json.dumps(event))
    async def send_system_message(self,content):
        event = {
            'type': 'system_message',
            'message': content,
            'timestamp': timezone.now().isoformat(),
            'sender': '系统通知',
        }
        await self.channel_layer.group_send(self.group_id, event)











